#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <stdint.h>
#include <arm_neon.h>
#include <arm_sve.h>
#include <unistd.h>

#define CAPTURE_DATA 3958

#define ALIGNED(x)   __attribute__((__aligned__(x)))
#define L1_CACHE_LINE_SHIFT (6)
#define ___cacheline_aligned_smp    ALIGNED((1 << L1_CACHE_LINE_SHIFT))

struct cacheline_padding
{
    char x[0];
}___cacheline_aligned_smp;

#define CACHELINE_PADDING(name) struct cacheline_padding name

typedef struct {
    float I;
    float Q;
}F32_IQ_STRU;

F32_IQ_STRU input0[CAPTURE_DATA] = {
    #include "input-1.txt"
};
F32_IQ_STRU input1[CAPTURE_DATA] = {
    #include "input-2.txt"
};
F32_IQ_STRU output[CAPTURE_DATA] = {0};


void data_correlation_caculate(F32_IQ_STRU * input0,F32_IQ_STRU* input1,F32_IQ_STRU* output)
{
    F32_IQ_STRU stRefTemp[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    F32_IQ_STRU stRxTemp[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    F32_IQ_STRU stCorrPTR[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    unsigned int i=0,j=0;
    unsigned int datalen = 0;
    unsigned int copysize = 0;
    float factor = 1.0f / 32768;
    datalen = CAPTURE_DATA + CAPTURE_DATA - 1;
    copysize = CAPTURE_DATA * sizeof(F32_IQ_STRU);
    
    memset(stRefTemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stRxTemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stCorrPTR,0,datalen*sizeof(F32_IQ_STRU));

    memcpy(&stRefTemp[0],&input0[0],copysize);
    memcpy(&stRxTemp[CAPTURE_DATA-1],&input1[0],copysize);

    for(i = 0;i < datalen;i++)
    {
        for(j = 0;j < i+1;j++)
        {
            stCorrPTR[i].I = stCorrPTR[i].I + stRefTemp[j].I * stRxTemp[datalen-1-(i-j)].I + stRefTemp[j].Q * stRxTemp[datalen-1-(i-j)].Q;
            stCorrPTR[i].Q = stCorrPTR[i].Q - stRefTemp[j].I * stRxTemp[datalen-1-(i-j)].Q + stRefTemp[j].Q * stRxTemp[datalen-1-(i-j)].I;
        }
        stCorrPTR[i].I = stCorrPTR[i].I * factor;
        stCorrPTR[i].Q = stCorrPTR[i].Q * factor; 
    }

    memcpy(&output[0],&stCorrPTR[0],CAPTURE_DATA * sizeof(F32_IQ_STRU));
}

void data_correlation_caculate_pipeline(F32_IQ_STRU * input0,F32_IQ_STRU* input1,F32_IQ_STRU* output)
{
    F32_IQ_STRU stRefTemp[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    F32_IQ_STRU stRxTemp[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    F32_IQ_STRU stCorrPTR[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    F32_IQ_STRU stRevRxtemp[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    register unsigned int i=0,j=0;
    float factor = 1.0f / 32768;
    unsigned int datalen = 0;
    unsigned int copysize = 0;
    register unsigned int k=0;
    datalen = CAPTURE_DATA + CAPTURE_DATA - 1;
    copysize = CAPTURE_DATA * sizeof(F32_IQ_STRU);

    memset(stRevRxtemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stRefTemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stRxTemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stCorrPTR,0,datalen*sizeof(F32_IQ_STRU));

    memcpy(&stRefTemp[0],&input0[0],copysize);
    memcpy(&stRxTemp[CAPTURE_DATA-1],&input1[0],copysize);

    unsigned int chunk = datalen >> 2;
    unsigned int remainder = datalen & 3;
    unsigned int last_index = datalen - 1;
    unsigned int chunkdatanum = chunk * 4;
    register unsigned int k_1 = 0,k_2=0,k_3=0;
    for(k = 0;k < chunkdatanum;k +=4)
    {
        k_1 = k+1;
        k_2 = k+2;
        k_3 = k+3;
        stRevRxtemp[k].I = stRxTemp[last_index - k].I;
        stRevRxtemp[k].Q = stRxTemp[last_index - k].Q;
        
        stRevRxtemp[k_1].I = stRxTemp[last_index - k_1].I;
        stRevRxtemp[k_1].Q = stRxTemp[last_index - k_1].Q;
        
        stRevRxtemp[k_2].I = stRxTemp[last_index - k_2].I;
        stRevRxtemp[k_2].Q = stRxTemp[last_index - k_2].Q;

        stRevRxtemp[k_3].I = stRxTemp[last_index - k_3].I;
        stRevRxtemp[k_3].Q = stRxTemp[last_index - k_3].Q;
    }

    if(remainder)
    {
        for(k = chunk * 4; k < datalen;k++)
        {
            stRevRxtemp[k].I = stRxTemp[last_index - k].I;
            stRevRxtemp[k].Q = stRxTemp[last_index - k].Q;
        }
    }

    k = 0;
    register float sum_i = 0;
    register float sum_q = 0;

    register float sum0_i = 0;
    register float sum0_q = 0;

    register float sum1_i = 0;
    register float sum1_q = 0;
    
    register float sum2_i = 0;
    register float sum2_q = 0;
    
    register float sum3_i = 0;
    register float sum3_q = 0;

    register unsigned int end = 0;
    register unsigned int j_1=0,j_2=0,j_3=0;
    for(i = 0;i < datalen;i++)
    {
        j = 0;
        sum_i = 0;
        sum_q = 0;
        end = i+1;
        for(;j + 3 < end;j +=4)
        {
            k = i - j;
            k_1 = k-1;
            k_2 = k-2;
            k_3 = k-3;

            j_1 = j+1;
            j_2 = j+2;
            j_3 = j+3;

            sum0_i = stRefTemp[j].I * stRevRxtemp[k].I + stRefTemp[j].Q * stRevRxtemp[k].Q;
            sum0_q = stRefTemp[j].Q * stRevRxtemp[k].I - stRefTemp[j].I * stRevRxtemp[k].Q;
            
            sum1_i = stRefTemp[j_1].I * stRevRxtemp[k_1].I + stRefTemp[j_1].Q * stRevRxtemp[k_1].Q;
            sum1_q = stRefTemp[j_1].Q * stRevRxtemp[k_1].I - stRefTemp[j_1].I * stRevRxtemp[k_1].Q;
            
            sum2_i = stRefTemp[j_2].I * stRevRxtemp[k_2].I + stRefTemp[j_2].Q * stRevRxtemp[k_2].Q;
            sum2_q = stRefTemp[j_2].Q * stRevRxtemp[k_2].I - stRefTemp[j_2].I * stRevRxtemp[k_2].Q;

            sum3_i = stRefTemp[j_3].I * stRevRxtemp[k_3].I + stRefTemp[j_3].Q * stRevRxtemp[k_3].Q;
            sum3_q = stRefTemp[j_3].Q * stRevRxtemp[k_3].I - stRefTemp[j_3].I * stRevRxtemp[k_3].Q;
            sum_i += sum0_i + sum1_i + sum2_i + sum3_i;
            sum_q += sum0_q + sum1_q + sum2_q + sum3_q;
        }
        for(;j< end;j++)
        {
            k = i - j;
            sum_i += stRefTemp[j].I * stRevRxtemp[k].I + stRefTemp[j].Q * stRevRxtemp[k].Q;
            sum_q += stRefTemp[j].Q * stRevRxtemp[k].I - stRefTemp[j].I * stRevRxtemp[k].Q;
        }
        stCorrPTR[i].I = sum_i * factor;
        stCorrPTR[i].Q = sum_q * factor; 
    }
    memcpy(&output[0],&stCorrPTR[0],CAPTURE_DATA * sizeof(F32_IQ_STRU));
}

void data_correlation_caculate_neon(F32_IQ_STRU * input0,F32_IQ_STRU* input1,F32_IQ_STRU* output)
{
    F32_IQ_STRU stRefTemp[CAPTURE_DATA+CAPTURE_DATA-1];
    F32_IQ_STRU stRxTemp[CAPTURE_DATA+CAPTURE_DATA-1];
    F32_IQ_STRU stCorrPTR[CAPTURE_DATA+CAPTURE_DATA-1];
    register unsigned int i=0;
    float factor = 1.0f / 32768;
    unsigned int datalen = 0;
    unsigned int copysize = 0;
    register unsigned int k=0;
    register F32_IQ_STRU* pstRefTemp = NULL;
    register F32_IQ_STRU* pstRefTempEnd = NULL;
    register F32_IQ_STRU* pstRxTemp = NULL;
    register float32x4_t sum_Q_vec;// 8 int , 4 iindex 
    register float32x4_t sum_I_vec;

    register float32x4_t sum_I_vec1;
    register float32x4_t sum_I_vec2;
    register float32x4_t sum_I_vec3;
    register float32x4_t sum_I_vec4;
    register float32x4_t sum_Q_vec1;
    register float32x4_t sum_Q_vec2;
    register float32x4_t sum_Q_vec3;
    register float32x4_t sum_Q_vec4;
    register float sum_i = 0;
    register float sum_q = 0;
    register unsigned int end = 0;
    register unsigned int last_index = 0;

    datalen = CAPTURE_DATA + CAPTURE_DATA - 1;
    copysize = CAPTURE_DATA * sizeof(F32_IQ_STRU);

    memset(stRefTemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stRxTemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stCorrPTR,0,datalen*sizeof(F32_IQ_STRU));

    memcpy(&stRefTemp[0],&input0[0],copysize);
    memcpy(&stRxTemp[CAPTURE_DATA-1],&input1[0],copysize);

    last_index = datalen - 1;
    for(i = 0;i < datalen;i++)
    {        
        sum_i = 0;
        sum_q = 0;
        end = i+1;
        k = last_index - i;
        pstRefTempEnd = &stRefTemp[end];
        pstRefTemp = &stRefTemp[0];
        pstRxTemp = &stRxTemp[k];
        
        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_I_vec));
        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_Q_vec));

        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_I_vec1));
        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_I_vec2));
        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_I_vec3));
        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_I_vec4));

        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_Q_vec1));
        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_Q_vec2));
        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_Q_vec3));
        asm volatile("eor %0.16b, %0.16b, %0.16b" : "=w" (sum_Q_vec4));
        
        for(;pstRefTemp + 15 < pstRefTempEnd ;pstRefTemp +=16,pstRxTemp +=16)
        {
            asm volatile(
                "ld2 {v0.4s, v1.4s}, [%[rx1]]       \n"
                "ld2 {v2.4s, v3.4s}, [%[ref1]]      \n"

                "ld2 {v4.4s, v5.4s}, [%[rx2]]       \n"
                "ld2 {v6.4s, v7.4s}, [%[ref2]]      \n"

                "ld2 {v8.4s, v9.4s}, [%[rx3]]       \n"
                "ld2 {v10.4s, v11.4s}, [%[ref3]]    \n"

                "ld2 {v12.4s, v13.4s}, [%[rx4]]     \n"
                "ld2 {v14.4s, v15.4s}, [%[ref4]]    \n"
                //========1========
                "fmla %[I_vec1].4s, v0.4s, v2.4s     \n"
                "fmla %[I_vec1].4s, v1.4s, v3.4s     \n"
                "fmla %[Q_vec1].4s, v3.4s, v0.4s     \n"
                "fmls %[Q_vec1].4s, v1.4s, v2.4s     \n"
                //========2========
                "fmla %[I_vec2].4s, v4.4s, v6.4s     \n"
                "fmla %[I_vec2].4s, v5.4s, v7.4s     \n"
                "fmla %[Q_vec2].4s, v7.4s, v4.4s     \n"
                "fmls %[Q_vec2].4s, v5.4s, v6.4s     \n"
                //========3========
                "fmla %[I_vec3].4s, v8.4s, v10.4s    \n"
                "fmla %[I_vec3].4s, v9.4s, v11.4s    \n"
                "fmla %[Q_vec3].4s, v11.4s, v8.4s    \n"
                "fmls %[Q_vec3].4s, v9.4s, v10.4s    \n"
                //========4========
                "fmla %[I_vec4].4s, v12.4s, v14.4s   \n"
                "fmla %[I_vec4].4s, v13.4s, v15.4s   \n"
                "fmla %[Q_vec4].4s, v15.4s, v12.4s   \n"
                "fmls %[Q_vec4].4s, v13.4s, v14.4s   \n"

                : [I_vec1] "+w" (sum_I_vec1), [Q_vec1] "+w" (sum_Q_vec1),
                  [I_vec2] "+w" (sum_I_vec2), [Q_vec2] "+w" (sum_Q_vec2),
                  [I_vec3] "+w" (sum_I_vec3), [Q_vec3] "+w" (sum_Q_vec3),
                  [I_vec4] "+w" (sum_I_vec4), [Q_vec4] "+w" (sum_Q_vec4)

                : [rx1] "r" ((float*)pstRxTemp), [ref1] "r" ((float*)pstRefTemp),
                  [rx2] "r" ((float*)(pstRxTemp + 4)), [ref2] "r" ((float*)(pstRefTemp + 4)),
                  [rx3] "r" ((float*)(pstRxTemp + 8)), [ref3] "r" ((float*)(pstRefTemp + 8)),
                  [rx4] "r" ((float*)(pstRxTemp + 12)), [ref4] "r" ((float*)(pstRefTemp + 12))

                : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8","v9","v10",
                  "v11","v12","v13","v14","v15","memory"
            );
        }
        for(;pstRefTemp + 7 < pstRefTempEnd ;pstRefTemp +=8,pstRxTemp +=8)
        {
            asm volatile(
                "ld2 {v0.4s, v1.4s}, [%[rx1]]       \n"
                "ld2 {v2.4s, v3.4s}, [%[ref1]]      \n"
                "ld2 {v4.4s, v5.4s}, [%[rx2]]       \n"
                "ld2 {v6.4s, v7.4s}, [%[ref2]]      \n"
                //========1========
                "fmla %[I_vec1].4s, v0.4s, v2.4s     \n"
                "fmla %[I_vec1].4s, v1.4s, v3.4s     \n"
                "fmla %[Q_vec1].4s, v3.4s, v0.4s     \n"
                "fmls %[Q_vec1].4s, v1.4s, v2.4s     \n"
                //========2========
                "fmla %[I_vec2].4s, v4.4s, v6.4s     \n"
                "fmla %[I_vec2].4s, v5.4s, v7.4s     \n"
                "fmla %[Q_vec2].4s, v7.4s, v4.4s     \n"
                "fmls %[Q_vec2].4s, v5.4s, v6.4s     \n"
                : [I_vec1] "+w" (sum_I_vec1), [Q_vec1] "+w" (sum_Q_vec1),
                  [I_vec2] "+w" (sum_I_vec2), [Q_vec2] "+w" (sum_Q_vec2)
                : [rx1] "r" ((float*)pstRxTemp), [ref1] "r" ((float*)pstRefTemp),
                  [rx2] "r" ((float*)(pstRxTemp + 4)), [ref2] "r" ((float*)(pstRefTemp + 4))
                : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "memory"
            );
        }
        for(;pstRefTemp + 3 < pstRefTempEnd ;pstRefTemp += 4,pstRxTemp += 4)
        {
            asm volatile(
                "ld2 {v0.4s,v1.4s},[%[rx]]      \n"
                "ld2 {v2.4s,v3.4s},[%[ref]]     \n"
                "fmla %[I_vec].4s,v0.4s,v2.4s    \n"
                "fmla %[I_vec].4s,v1.4s,v3.4s    \n"
                "fmla %[Q_vec].4s,v3.4s,v0.4s    \n"
                "fmls %[Q_vec].4s,v1.4s,v2.4s    \n"
                :[I_vec]"+w"(sum_I_vec1),[Q_vec]"+w"(sum_Q_vec1)
                :[rx]"r"((float*)pstRxTemp),[ref]"r"((float*)pstRefTemp)
                :"v0", "v1", "v2", "v3", "memory"
            );
        }
#if 0        
        sum_I_vec = vaddq_s32(vaddq_s32(sum_I_vec1,sum_I_vec2),vaddq_s32(sum_I_vec3,sum_I_vec4));
        sum_Q_vec = vaddq_s32(vaddq_s32(sum_Q_vec1,sum_Q_vec2),vaddq_s32(sum_Q_vec3,sum_Q_vec4));
        sum_i = vaddvq_s32(sum_I_vec);
        sum_q = vaddvq_s32(sum_Q_vec);
#endif
        asm volatile (
            //sum_I_vec
            "fadd v31.4s, %[I_vec1].4s, %[I_vec2].4s   \n"    // v31 = sum_I_vec1 + sum_I_vec2
            "fadd v30.4s, %[I_vec3].4s, %[I_vec4].4s   \n"    // v30 = sum_I_vec3 + sum_I_vec4
            "fadd v31.4s, v31.4s, v30.4s               \n"       // sum_I_vec = v30 + v31
            //sum_Q_vec  
            "fadd v29.4s, %[Q_vec1].4s, %[Q_vec2].4s   \n"    // v29 = sum_Q_vec1 + sum_Q_vec2
            "fadd v28.4s, %[Q_vec3].4s, %[Q_vec4].4s   \n"    // v28 = sum_Q_vec3 + sum_Q_vec4
            "fadd v29.4s, v29.4s, v28.4s               \n"    // sum_Q_vec = v29 + v28
            "faddp v31.4s, v31.4s, v31.4s              \n"    
            "faddp v31.4s, v31.4s, v31.4s              \n"    
            "faddp v29.4s, v29.4s, v29.4s              \n"    
            "faddp v29.4s, v29.4s, v29.4s              \n"  
            "fmov %w[SUM_I], s31                 \n"
            "fmov %w[SUM_Q], s29                 \n"
            : [SUM_I]"=r"(sum_i), [SUM_Q]"=r"(sum_q)
            : [I_vec1]"w"(sum_I_vec1), [I_vec2]"w"(sum_I_vec2), [I_vec3]"w"(sum_I_vec3), [I_vec4]"w"(sum_I_vec4),
              [Q_vec1]"w"(sum_Q_vec1), [Q_vec2]"w"(sum_Q_vec2), [Q_vec3]"w"(sum_Q_vec3), [Q_vec4]"w"(sum_Q_vec4)
            : "v31", "v30", "v29", "v28", "memory"
        );
        for(;pstRefTemp < pstRefTempEnd;pstRefTemp++,pstRxTemp++)
        {    
            sum_i += pstRefTemp->I * pstRxTemp->I + pstRefTemp->Q * pstRxTemp->Q;
            sum_q += pstRefTemp->Q * pstRxTemp->I - pstRefTemp->I * pstRxTemp->Q;
        }

        stCorrPTR[i].I = sum_i * factor;
        stCorrPTR[i].Q = sum_q * factor; 
    }
    memcpy(&output[0],&stCorrPTR[0],CAPTURE_DATA * sizeof(F32_IQ_STRU));
}

__attribute__((optimize("O3"))) void data_correlation_caculate_o3(F32_IQ_STRU * input0,F32_IQ_STRU* input1,F32_IQ_STRU* output)
{
    F32_IQ_STRU stRefTemp[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    F32_IQ_STRU stRxTemp[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    F32_IQ_STRU stCorrPTR[CAPTURE_DATA+CAPTURE_DATA-1] = {0};
    unsigned int i=0,j=0;
    unsigned int datalen = 0;
    unsigned int copysize = 0;
    float factor = 1.0 / 32768;
    datalen = CAPTURE_DATA + CAPTURE_DATA - 1;
    copysize = CAPTURE_DATA * sizeof(F32_IQ_STRU);
    
    memset(stRefTemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stRxTemp,0,datalen*sizeof(F32_IQ_STRU));
    memset(stCorrPTR,0,datalen*sizeof(F32_IQ_STRU));

    memcpy(&stRefTemp[0],&input0[0],copysize);
    memcpy(&stRxTemp[CAPTURE_DATA-1],&input1[0],copysize);

    for(i = 0;i < datalen;i++)
    {
        for(j = 0;j < i+1;j++)
        {
            stCorrPTR[i].I = stCorrPTR[i].I + stRefTemp[j].I * stRxTemp[datalen-1-(i-j)].I + stRefTemp[j].Q * stRxTemp[datalen-1-(i-j)].Q;
            stCorrPTR[i].Q = stCorrPTR[i].Q - stRefTemp[j].I * stRxTemp[datalen-1-(i-j)].Q + stRefTemp[j].Q * stRxTemp[datalen-1-(i-j)].I;
        }
        stCorrPTR[i].I = stCorrPTR[i].I * factor;
        stCorrPTR[i].Q = stCorrPTR[i].Q * factor; 
    }
    memcpy(&output[0],&stCorrPTR[0],CAPTURE_DATA * sizeof(F32_IQ_STRU));
}

int main()
{
    struct timespec start, end;
    double time_used;
    unsigned int idx = 0;
    double sum = 0;
    for(;;)
    {
        sum = 0;
        memset(output,0,CAPTURE_DATA*sizeof(F32_IQ_STRU));
        clock_gettime(CLOCK_MONOTONIC, &start);
        data_correlation_caculate(input0,input1,output);
        clock_gettime(CLOCK_MONOTONIC, &end);
        time_used = (end.tv_sec - start.tv_sec) * 1000000.0 + 
                    (end.tv_nsec - start.tv_nsec) / 1000.0;
        for(idx = 0; idx < CAPTURE_DATA;idx ++)
        {
            sum +=output[idx].I * output[idx].I + output[idx].Q * output[idx].Q;
        }
        printf("%-25s: %12.3f us, sum: %15lf\n", "C ori time", time_used, sum);
    //=====================================================================================//
        sum = 0;
        memset(output,0,CAPTURE_DATA*sizeof(F32_IQ_STRU));
        clock_gettime(CLOCK_MONOTONIC, &start);
        data_correlation_caculate_pipeline(input0,input1,output);
        clock_gettime(CLOCK_MONOTONIC, &end);
        time_used = (end.tv_sec - start.tv_sec) * 1000000.0 + 
                    (end.tv_nsec - start.tv_nsec) / 1000.0;
        for(idx = 0; idx < CAPTURE_DATA;idx ++)
        {
            sum +=output[idx].I * output[idx].I + output[idx].Q * output[idx].Q;
        }
        printf("%-25s: %12.3f us, sum: %15lf\n", "C pipeline unrolling time", time_used, sum);
    //=====================================================================================//
        sum = 0;
        memset(output,0,CAPTURE_DATA*sizeof(F32_IQ_STRU));
        clock_gettime(CLOCK_MONOTONIC, &start);
        data_correlation_caculate_neon(input0,input1,output);
        clock_gettime(CLOCK_MONOTONIC, &end);
        time_used = (end.tv_sec - start.tv_sec) * 1000000.0 + 
                    (end.tv_nsec - start.tv_nsec) / 1000.0;
        for(idx = 0; idx < CAPTURE_DATA;idx ++)
        {
            sum +=output[idx].I * output[idx].I + output[idx].Q * output[idx].Q;
        }
        printf("%-25s: %12.3f us, sum: %15lf\n", "C neon asm time", time_used, sum);
    //=====================================================================================//
        sum = 0;
        memset(output,0,CAPTURE_DATA*sizeof(F32_IQ_STRU));
        clock_gettime(CLOCK_MONOTONIC, &start);
        data_correlation_caculate_o3(input0,input1,output);
        clock_gettime(CLOCK_MONOTONIC, &end);
        time_used = (end.tv_sec - start.tv_sec) * 1000000.0 + 
                    (end.tv_nsec - start.tv_nsec) / 1000.0;
        for(idx = 0; idx < CAPTURE_DATA;idx ++)
        {
            sum +=output[idx].I * output[idx].I + output[idx].Q * output[idx].Q;
        }
        printf("%-25s: %12.3f us, sum: %15lf\n", "C -O3 time", time_used, sum);
        printf("=====================================================================================\n");
        sleep(2);
    }
    return 0;
}

